package org.tea.crawl.biz.domain.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.tea.crawl.biz.configuration.TargetDirConfiguration;
import org.tea.crawl.biz.domain.dto.DomDataDto;
import org.tea.crawl.biz.domain.entity.TeaItemUrl;
import org.tea.crawl.biz.domain.enums.ParseState;
import org.tea.crawl.biz.domain.repository.TeaItemUrlRepository;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author lxh
 */
@Service
@Transactional
public class CrawlItemUrlService {

    private final static Logger log = LoggerFactory.getLogger(CrawlItemUrlService.class);

    private final Lock lock = new ReentrantLock();

    @Resource
    private TeaItemUrlRepository teaItemUrlRepository;

    @Resource
    private TargetDirConfiguration dirConfiguration;

    public TeaItemUrl findNextItemUrl() {
        ThreadLocalRandom random = ThreadLocalRandom.current();
        List<TeaItemUrl> items = teaItemUrlRepository.findUnParsedItems();
        if (CollectionUtils.isEmpty(items)) {
            return null;
        }

        int cnt = 0;
        lock.lock();
        try {
            while (cnt < items.size()) {
                int i = random.nextInt(0, items.size());
                TeaItemUrl itemUrl = teaItemUrlRepository.findById(items.get(i).getId());
                if (ParseState.EMPTY.code.equals(itemUrl.getParseState())) {
                    itemUrl.setParseState(ParseState.PARSED.code);
                    teaItemUrlRepository.save(itemUrl);
                    return itemUrl;
                }
                cnt++;
            }
        } finally {
            lock.unlock();
        }
        return null;
    }

    public void saveDomContent(DomDataDto dataDto) {
        lock.lock();
        try {
            dataDto.setParsed("1");
            dataDto.setParseState(ParseState.PARSED.code);
            teaItemUrlRepository.save(dataDto);
        } finally {
            lock.unlock();
        }

        writeDom(dataDto.getId(), dataDto.getDomContent());
    }

    protected void writeDom(Long id, String domContent) {
        Path path = Paths.get(dirConfiguration.getDataDir() + File.separator + id);
        File file = path.toFile();
        if (!file.exists()) {
            try {
                file.getParentFile().mkdirs();
                boolean newFile = file.createNewFile();
                if (!newFile) {
                    throw new RuntimeException("创建文件失败");
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        try (FileWriter writer = new FileWriter(file)) {
            writer.write(domContent);
            writer.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
